package org.computeiros.xmakel.assistents;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;

public class XMLEditor extends StyledText {
	private static final int STYLE_TAG = 0;
	private static final int STYLE_TAG_MISS = 7;
	private static final int STYLE_CDATA = 1;
	private static final int STYLE_ATTVALUEE = 3;
	private static final int STYLE_VARIABLE = 4;
	private static final int STYLE_ITERATOR = 5;
	private static final int STYLE_DEFAULT= 6;
	
	private static final String PATTERN_TAG;
	private static final String PATTERN_TAG_MISS;
	private static final String PATTERN_CDATA;
	private static final String PATTERN_VARIABLE;
	
	private static final String PATTERN_ITERATOR;
	
	static{
		PATTERN_TAG = "</?[a-z][a-z0-9]*[^<>]*>";
		PATTERN_TAG_MISS = "(?>%TAG%.*?(?=<%TAG%|</%TAG%>|\\z))(?!</%TAG%>)"; 
		PATTERN_VARIABLE = "\\$\\{\\w+\\.\\w+\\}";
		PATTERN_CDATA = "<\\!\\[CDATA\\[|\\]\\]>";
		
		StringBuilder patternIte = new StringBuilder();
		patternIte.append(VariableList.VLR_ITECARROS_START);
		patternIte.append("|");
		patternIte.append(VariableList.VLR_ITECARROS_END);
		patternIte.append("|");
		patternIte.append(VariableList.VLR_ITEFOTOS_START);
		patternIte.append("|");
		patternIte.append(VariableList.VLR_ITEFOTOS_END);
		patternIte.append("|");
		patternIte.append(VariableList.VLR_ITEOPC_START);
		patternIte.append("|");
		patternIte.append(VariableList.VLR_ITEOPC_END);
		
		PATTERN_ITERATOR = patternIte.toString();
	}
	
	public XMLEditor(Composite parent, int style) {
		super(parent, style);
		
		addModifyListener(new TextEditorModifyListener());
	}
	
	private void setStyleText(int start, int length, int styleType){
		StyleRange style = new StyleRange();
		Display display = getShell().getDisplay(); 
		switch(styleType){
			case STYLE_TAG:	
				style.foreground = display.getSystemColor(SWT.COLOR_BLUE);
				break;
			
			case STYLE_TAG_MISS:
				style.foreground = display.getSystemColor(SWT.COLOR_RED);
				break;
				
				
			case STYLE_CDATA:
				style.foreground = display.getSystemColor(SWT.COLOR_MAGENTA);
				break;
				
			case STYLE_ATTVALUEE:
				style.foreground = display.getSystemColor(SWT.COLOR_CYAN);
				break;
				
			case STYLE_VARIABLE:
				style.foreground = display.getSystemColor(SWT.COLOR_DARK_GREEN);
				style.fontStyle = SWT.BOLD;
				break;
				
			case STYLE_ITERATOR:
				style.foreground = display.getSystemColor(SWT.COLOR_RED);
				style.fontStyle = SWT.BOLD;
				break;
			
			case STYLE_DEFAULT:
				style.foreground = display.getSystemColor(SWT.COLOR_BLACK);
				break;
			
		}
		style.start = start;
		style.length = length;
		
		setStyleRange(style);
	}
	
	private void decorateText(){
		String text = getText();
		Matcher mTag = Pattern.compile(PATTERN_TAG).matcher(text);
		
		while(mTag.find()){
			String found = mTag.group();
			int start = text.indexOf(found);
			setStyleText(start, found.length(), STYLE_TAG);
		}
		
		Matcher mTagMiss = Pattern.compile(PATTERN_TAG_MISS).matcher(text);
		while(mTagMiss.find()){
			String found = mTagMiss.group();
			int start = text.indexOf(found);
			setStyleText(start, found.length(), STYLE_TAG_MISS);
		}
		
		Matcher mAtt = Pattern.compile(PATTERN_VARIABLE).matcher(text);
		while(mAtt.find()){
			String found = mAtt.group();
			int start = text.indexOf(found);
			setStyleText(start, found.length(), STYLE_VARIABLE);
		}
		
		Matcher mIte = Pattern.compile(PATTERN_ITERATOR).matcher(text);
		while(mIte.find()){
			String found = mIte.group();
			int start = text.indexOf(found);
			setStyleText(start, found.length(), STYLE_ITERATOR);
		}
		
		Matcher mCdata = Pattern.compile(PATTERN_CDATA, Pattern.DOTALL|Pattern.MULTILINE).matcher(text);
		while(mCdata.find()){
			String found = mCdata.group();
			int start = text.indexOf(found);
			setStyleText(start, found.length(), STYLE_CDATA);
		}
		
	}
	
	private class TextEditorModifyListener implements ModifyListener{

		@Override
		public void modifyText(ModifyEvent e) {
			setStyleText(0, getText().length(), STYLE_DEFAULT);
			decorateText();
		}
		
	}
}
